<?php

/**
 * 一、定义
 *策略模式定义了一系列的算法，并将每一个算法封装起来，而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
 *二、概述
 *应用场景：
 *　　1、 多个类只区别在表现行为不同，可以使用Strategy模式，在运行时动态选择具体要执行的行为。
 *　  2、 需要在不同情况下使用不同的策略(算法)，或者策略还可能在未来用其它方式来实现。
 *　　3、 对客户隐藏具体策略(算法)的实现细节，彼此完全独立。
 *
 * 三、代码实现
 * 需求：商场收费系统，根据商品的单价和数量，得出的总结可以"正常收费", "打八折","满300返100", "打七折", "打五折"等等。
 */
abstract class strategyPattern{
    abstract function getPayMoney($money);
}

//正常收费类
class DiscountPattern extends strategyPattern{
    public function getPayMoney($money)
    {
        // TODO: Implement getPayMoney() method.
       return $money;
    }
}

//满减类
class MoneyPattern extends strategyPattern{
    public $money;

    public function getPayMoney($money)
    {
        $this->money=$money;
        return $this->manage();
        // TODO: Implement getPayMoney() method.
    }

    public function manage(){
        if ($this->money>=1000){
            return $this->money-50;
        }else{
            return $this->money;
        }
    }
}

//对外接口
class PayMoney{
    public function pay($money,$type){
        $total=0;
        switch ($type){
            case 1:
                $obj=new MoneyPattern();
                $total=$obj->getPayMoney($money);
                break;
            case 2:
                $obj=new DiscountPattern();
                $total=$obj->getPayMoney($money);
                break;
        }
        return $total;
    }
}

$testObj=new PayMoney();
$payPrice=$testObj->pay(1000);
/***************************通过工厂模式实现***************************/
abstract class PayMoneyAbstract{

    abstract  function getPayMoney($moeny);
}

class DiscountPatternData extends PayMoneyAbstract{
    public function getPayMoney($moeny)
    {
        return $moeny;
        // TODO: Implement getPayMoney() method.
    }
}

class MoneyPatternData extends PayMoneyAbstract{
    public $money;
    public function getPayMoney($moeny)
    {
        $this->money=$moeny;
        return $this->manage();
        // TODO: Implement getPayMoney() method.
    }
    public function manage(){
        if ($this->money>=1000){
            return $this->money-50;
        }else{
            return $this->money;
        }
    }
}

class Factory{
    public function pay($type){
        switch ($type){
            case 1:
                $obj=new MoneyPattern();
                break;
            case 2:
                $obj=new DiscountPattern();
                break;
            default:
                $obj=null;
        }
        return $obj;
    }
}
$testObj=new Factory();
$payPriceObj=$testObj->pay(1);
$payPrice=$payPriceObj->getPayMoney(100);

/*********************************************************
 * 由此可见他们的区别：
 * 他们返回的内容不同，
 * 工厂是返回不同的实例给客户端，
 * 而策略的实例只是为了自己的类使用，
 * 他是根据参数返回算法的结果GetResult，
 * 因此他们区别是目的不同，一个是为了返回实例，
 * 一个是为了封装不同的算法，适应算法的变化。
 */